package com.shuke.sk_worm.tool;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.druid.util.StringUtils;
import com.shuke.sk_worm.Mapper.SkShopInfoMapper;
import com.shuke.sk_worm.consts.AbnormalTypeEnum;
import com.shuke.sk_worm.consts.ShopPlatformEnum;
import com.shuke.sk_worm.domain.*;
import com.shuke.sk_worm.dto.WebDriverListDto;
import com.shuke.sk_worm.service.Impl.*;
import com.shuke.sk_worm.service.SkAccountsService;
import com.shuke.sk_worm.service.SkRealDataService;
import com.shuke.sk_worm.service.SysUserService;
import com.shuke.sk_worm.vo.HisKpiDataVo;
import com.shuke.sk_worm.vo.IpPoolVo;
import com.shuke.sk_worm.vo.RealDataVo;
import com.shuke.sk_worm.vo.ShopInfoListVo;
import lombok.SneakyThrows;
import org.apache.log4j.Logger;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.xml.crypto.Data;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Component
public class Worm{

    final String url = "https://fxg.jinritemai.com/login/common";

    public String hisDataUrl = "https://pigeon.jinritemai.com/backstage/get_historical_staff_statistics_v2?page=1&size=1000&startTime=%d&endTime=%d&queryStaffName=%s";

    public String realDataUrl = "https://pigeon.jinritemai.com/backstage/getRealtimeStaffStatistics?page=1&size=1000&queryStaffName=%s";

    //public String ipPoolUrl = "http://tiqu.pyhttp.taolop.com/getflowip?count=1&neek=106218&type=1&sep=3&sb=&ip_si=1&mr=0";
    public String ipPoolUrl = "http://api.shenlongip.com/ip?key=b91qbg40&pattern=txt&count=1&split=%5Cn&mr=1&protocol=1&sign=52a366b14bf52d02df5911b9f6273814";

    @Autowired
    private SkShopInfoMapper skShopInfoMapper;

    @Autowired
    private SkAccountsService accountsService;


    //静态初使化 一个工具类  这样是为了在spring初使化之前
    private static Worm worm;


    //private final String googleDriverPath = "D:/chromedriver.exe";

    private final String googleDriverPath = "D:/project/chromedriver/chromedriver.exe";

    //private final String clintPath = "C:\\Users\\daying\\AppData\\Local\\Google\\Chrome\\User Data\\";

    private final String clintPath = "C:\\Users\\Administrator\\AppData\\Local\\Google\\Chrome\\User Data\\";


    private int reTryNum = 0;

    private int maxRetryNum = 3;

    private static final Logger logger =  Logger.getLogger(Worm.class);

    /**
     * IP 生成时间
     */
    private Long IpTime = 0L;

    private String Ip;

    //浏览器用户数
    //private List<Integer> userSort = new LinkedList<>(Arrays.asList(0,1,2,3,4,5,6,7,8,9));

    private List<Integer> userSort = new LinkedList<>(Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15));

    //WebDriver池子
    private List<WebDriverListDto> webDriverListDtos = new ArrayList<>();

    //退出webDriver时间
    private Long webDriverExpiredTime = 180 * 1000L;

    /**
     * IP池子
     */
    private List<String> IpPool;

    //IP切换时间
    private Long fiveMin = 50 * 1000L;

    //关键 3  通过@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作
    @PostConstruct
    public void init() {
        worm = this;
        // 初使化时将已静态化的configParam实例化
        worm.skShopInfoMapper = this.skShopInfoMapper;
        worm.accountsService = this.accountsService;
    }

    public String getProxyIp(){
        String ip = HttpUtil.get(ipPoolUrl);
        return ip.replaceAll("\r", "");
    }

    public List<String> ipPool(){
        List<String> ipArray = new ArrayList<>();
        try {
            //String ips = HttpUtil.get(ipPoolUrl);
           /* JSONObject jsonObject = JSONUtil.parseObj(ips);
            if (!"0".equals(String.valueOf(jsonObject.get("code")))){
                Thread.sleep(1000 * 2);
                ips = HttpUtil.get(ipPoolUrl);
                jsonObject = JSONUtil.parseObj(ips);
            }

            List<IpPoolVo> ipPoolVos = JSONUtil.toList(JSONUtil.parseArray(jsonObject.get("data")), IpPoolVo.class);
            ipPoolVos.forEach(vo->{
                ipArray.add(vo.getIp() + ":" + vo.getPort());
            });*/
            /*String[] ipA = ips.split("\n");
            for (String ip : ipA){
                ipArray.add(ip);
            }*/
            ipArray.add("175.6.170.66:50006");
            ipArray.add("36.40.75.44:50000");
            ipArray.add("203.33.202.64:50003");
            ipArray.add("36.41.186.135:50006");
            ipArray.add("203.33.203.189:50001");
            ipArray.add("175.6.74.53:50003");
            ipArray.add("101.89.133.204:50009");
            ipArray.add("42.248.121.94:50005");
            ipArray.add("124.232.193.189:50001");
            ipArray.add("175.6.170.178:50007");
            //ipArray.add("localhost"); //本地的ip地址设为空
        }catch (Exception e){

        }
        return ipArray;
    }

    public synchronized void incrementUserSort(Integer sort) {
        if (!this.userSort.contains(sort) && sort !=null){
            this.userSort.add(sort);
        }
    }

    public synchronized Integer getUserSort() {
        System.out.print("this.userSort : " + this.userSort);
        Integer userSort = this.userSort.get(0);
        this.userSort.remove(0);
        return userSort;
    }

    public synchronized void insertWebDriver(WebDriverListDto driverListDto){
        this.webDriverListDtos.add(driverListDto);
    }

    public synchronized void quitWebDriver(WebDriverListDto webDriver){
        this.webDriverListDtos.remove(webDriver);
    }

    public synchronized void quitWebDriver(){
        if (this.webDriverListDtos.isEmpty()){
            return;
        }
        Long timeMillis = System.currentTimeMillis();
        //System.out.print("线程池数组 " + this.webDriverListDtos);

        for (WebDriverListDto webDriverListDto : this.webDriverListDtos){
            if (timeMillis - webDriverListDto.getCreateTime() >= this.webDriverExpiredTime){
                logger.info("线程超时 ：" + webDriverListDto);
                if (webDriverListDto.getWebDriver() != null){
                    webDriverListDto.getWebDriver().quit();
                    logger.info("线程 退出 ：" + webDriverListDto.getCreateTime() + " 当前时间：" + timeMillis);
                }
                incrementUserSort(webDriverListDto.getUserSort());
                this.webDriverListDtos.remove(webDriverListDto);
            }
        }
    }


    public List<ShopInfoListVo> multiSaveToken(List<ShopInfoListVo> skShopInfos, Map<Long,SkShopCookie> shopCookieList){
        this.IpPool = ipPool(); //初始化IP列表
        this.Ip = this.IpPool.get(this.IpPool.size() - 1); //初始化IP
        this.IpTime = System.currentTimeMillis(); //初始化时间
        try {
            reTryNum++;

            ThreadPoolExecutor fixedThreadPool = new ThreadPoolExecutor(5, 5, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
            fixedThreadPool.allowCoreThreadTimeOut(true);

            List<ShopInfoListVo> retryShopList = new ArrayList<>();

            List<WebDriverListDto> driverListDtos = new ArrayList<>();

            List<ShopInfoListVo> saveCookieShop = new ArrayList<>();

            for (ShopInfoListVo shop : skShopInfos){
                Long nowTimeMillis = System.currentTimeMillis();  //时间戳
                //判断店铺的token生成时间超过2天
                Long nowTimeSecond = nowTimeMillis/1000;

                //判断店铺的token生成时间超过2天,并且是没有权限的账号（后面分配权限需要从新获取cookie）
                if (shopCookieList !=  null){
                    if (shopCookieList.containsKey(shop.getId()) &&
                            shopCookieList.get(shop.getId()).getInsertTime() >= nowTimeSecond.intValue() - 48 * 3600 &&
                            !shop.getAbnormalType().equals(AbnormalTypeEnum.AUTH_ABNORMAL)
                    ){
                        logger.info("token: 店铺：" + shop.getName() + "未失效");
                        continue;
                    }
                }

                saveCookieShop.add(shop);
            }

            AtomicInteger atomicInt = new AtomicInteger(saveCookieShop.size());//要执行的数据

            for (ShopInfoListVo shop : saveCookieShop) {

                Future<?> future = fixedThreadPool.submit(new Runnable() {

                    @Override
                    public void run() {
                        Integer sort = getUserSort(); //获取用户的编号

                        WebDriver webDriver = webDriver(sort);
                        if (webDriver == null){
                            return;
                        }
                        try {

                            WebDriverListDto driverListDto = new WebDriverListDto();
                            driverListDto.setCreateTime(System.currentTimeMillis());
                            driverListDto.setChildThread(Thread.currentThread());
                            driverListDto.setUserSort(sort);
                            driverListDto.setWebDriver(webDriver);
                            driverListDtos.add(driverListDto);

                            atomicInt.decrementAndGet();  //执行数量减1

                            ShopInfoListVo res = savaShopToken(shop, sort, webDriver);
                            if (res != null){
                                synchronized(retryShopList){
                                    retryShopList.add(res);
                                }
                            }
                        }catch (Exception e){

                        }finally {
                            webDriver.close();
                            webDriver.quit();
                        }

                    }
                });
            }

            fixedThreadPool.shutdown();

            while (!fixedThreadPool.awaitTermination(3 * 60 * 60, TimeUnit.SECONDS)) {
                System.out.print("等待执行结束 。。。。。。。。");
                Long nowTimeMillis = System.currentTimeMillis();  //时间戳
                driverListDtos.forEach(vo -> {
                    if (nowTimeMillis >= vo.getCreateTime() + webDriverExpiredTime){
                        if (vo.getChildThread().isAlive()){
                            logger.info("线程超时 ：" + vo);
                            if (vo.getWebDriver() != null){
                                vo.getWebDriver().quit(); //退出浏览器
                            }
                            vo.getChildThread().interrupt(); //中断线程

                        }
                        driverListDtos.remove(vo);
                    }
                });

            }

            /*if (!retryShopList.isEmpty() && reTryNum<maxRetryNum){ //从新执行一次
                Thread.sleep(1000 * 60 * 3);
                multiSaveToken(retryShopList, shopCookieList);
            }*/
            return retryShopList;
        }catch (Exception e){

        }
        return null;
    }

    public ShopInfoListVo savaShopToken(ShopInfoListVo shop, Integer sort, WebDriver webDriver){
        logger.info("save_token: 店铺：" + shop.getName());

        Long nowTimeMillis = System.currentTimeMillis();  //时间戳


        SkShopCookieServiceImpl cookieService = new SkShopCookieServiceImpl(); //店铺cookie

        System.out.print("sort number" + sort);
       /* WebDriver webDriver = webDriver(sort);  //driver对象

        if (webDriver == null){
            incrementUserSort(sort);
            return shop;
        }*/

        JavascriptExecutor javascriptExecutor = (JavascriptExecutor) webDriver; //js对象
        try{

            if (!login(webDriver, javascriptExecutor, shop, nowTimeMillis)) {
                webDriver.close();
                webDriver.quit();
                shopErrorLog(shop, "1", "登录失败", 1);
                logger.info("save_token: 店铺：" + shop.getName() + "登录失败");
                incrementUserSort(sort);
                return shop;
            }

            //选择店铺
            int status = checkShop(webDriver, javascriptExecutor, shop.getName());
            if (status == -1){
                shopErrorLog(shop, "1", "登录失败", 1);
                webDriver.close();
                webDriver.quit();
                logger.info("save_token: 店铺：" + shop.getName() + "未获取到店铺");
                incrementUserSort(sort);
                return shop;
            }
            if (status == -2){ //解除合约的店铺不重试
                webDriver.close();
                webDriver.quit();
                shopErrorLog(shop, "1", "店铺解除合约或未找到", 1);
                logger.info("save_token: 店铺：" + shop.getName() + "店铺解除合约或未找到");
                incrementUserSort(sort);
                return null;
            }

            Set<Cookie> cookies = webDriver.manage().getCookies();
            String cookieHeader = "";
            for (Cookie cookie : cookies) {
                cookieHeader += cookie.getName()+"="+cookie.getValue()+"; ";
            }
            Map<String, String> header = new HashMap<>();
            header.put("Cookie", cookieHeader);

            String url = String.format(hisDataUrl, nowTimeMillis - 86400 , nowTimeMillis, "");

            HttpResponse response = HttpUtil.createGet(url).addHeaders(header).execute();
            logger.info(response.body());
            JSONObject jsonObject = JSONUtil.parseObj(response.body());
            if ("10005".equals(String.valueOf(jsonObject.get("code")))) {
                //页面中部分的cookie会延迟加载
                Thread.sleep(1000 * 6);
                cookies = webDriver.manage().getCookies();
                for (Cookie cookie : cookies) {
                    cookieHeader += cookie.getName()+"="+cookie.getValue()+"; ";
                }
                header.put("Cookie", cookieHeader);
                response = HttpUtil.createGet(url).addHeaders(header).execute();
                logger.info(response.body());
                jsonObject = JSONUtil.parseObj(response.body());
                if ("10005".equals(String.valueOf(jsonObject.get("code")))){
                    webDriver.close();
                    webDriver.quit();
                    incrementUserSort(sort);
                    return shop;
                }
            }
            //存入店铺cookie
            List<SkShopCookie> shopCookie = new ArrayList<>();
            SkShopCookie skShopCookie = new SkShopCookie();
            skShopCookie.setCookie(cookieHeader);
            skShopCookie.setShopId(shop.getId());
            skShopCookie.setInsertTime(Integer.parseInt(String.valueOf(nowTimeMillis/1000)));
            shopCookie.add(skShopCookie);
            cookieService.saveBatch(shopCookie);
            webDriver.manage().deleteAllCookies();
        }catch (Exception e){
            incrementUserSort(sort);
            webDriver.close();
            webDriver.quit();
            return shop;
        }finally {
            incrementUserSort(sort);
            webDriver.close();
            webDriver.quit();
        }
        shopErrorLog(shop, "0", "", 0);
        return null;
    }

    /**
     *
     * @param shop 店铺信息
     * @param msg 错误信息
     */
    public void shopErrorLog(ShopInfoListVo shop, String status, String msg, Integer abnormalType){
        SkShopInfo shopInfo = new SkShopInfo();
        shopInfo.setId(shop.getId());
        shopInfo.setIsAbnormal(status);
        shopInfo.setAbnormalMsg(msg);
        shopInfo.setAbnormalType(abnormalType);
        if ("0".equals(status)){
            shopInfo.setErrorTime("");
        }else{
            if (StringUtils.isEmpty(shop.getErrorTime())){
                String pattern = "yyyy-MM-dd HH:mm:ss";
                SimpleDateFormat sdf = new SimpleDateFormat(pattern);
                shopInfo.setErrorTime(sdf.format(DateUtil.date()));
            }
        }
        worm.skShopInfoMapper.updateById(shopInfo);
    }

    /**
     *
     * @param skShopInfos
     */
    public void saveToken(List<ShopInfoListVo> skShopInfos){
        if (skShopInfos.isEmpty()){
            return;
        }

        this.IpPool = ipPool();
        this.IpTime = System.currentTimeMillis(); //初始化时间

        SkShopCookieServiceImpl cookieService = new SkShopCookieServiceImpl(); //店铺cookie

        List<ShopInfoListVo> retryShopList = new ArrayList<>();

        for (ShopInfoListVo shop : skShopInfos){
            logger.info("Save_TOKEN: 店铺：" + shop.getName());

            Long nowTimeMillis = System.currentTimeMillis();  //时间戳

            Long nowTimeSecond = nowTimeMillis/1000;

            WebDriver webDriver = webDriver();  //driver对象
            JavascriptExecutor javascriptExecutor = (JavascriptExecutor) webDriver; //js对象
            try{
                if (!login(webDriver, javascriptExecutor, shop, nowTimeMillis)) {
                    retryShopList.add(shop);
                    shopErrorLog(shop, "1", "登录失败", 1);
                    webDriver.close();
                    webDriver.quit();
                    continue;
                }

                //选择店铺
                int status = checkShop(webDriver, javascriptExecutor, shop.getName());
                if (status == -1){
                    shopErrorLog(shop, "1", "登录失败", 1);
                    retryShopList.add(shop);
                    webDriver.close();
                    webDriver.quit();
                    continue;
                }
                if (status == -2){ //解除合约的店铺不重试
                    webDriver.close();
                    webDriver.quit();
                    shopErrorLog(shop, "1", "店铺解除合约或未找到", 1);
                    continue;
                }

                //页面中部分的cookie会延迟加载
                Thread.sleep(1000 * 3);

                Set<Cookie> cookies = webDriver.manage().getCookies();
                String cookieHeader = "";
                for (Cookie cookie : cookies) {
                    cookieHeader += cookie.getName()+"="+cookie.getValue()+"; ";
                }
                Map<String, String> header = new HashMap<>();

                header.put("Cookie", cookieHeader);
                logger.info(cookieHeader);
                String url = String.format(hisDataUrl, nowTimeMillis - 86400 , nowTimeMillis, "");

                HttpResponse response = HttpUtil.createGet(url).addHeaders(header).execute();
                logger.info(response.body());
                JSONObject jsonObject = JSONUtil.parseObj(response.body());
                if (!"0".equals(String.valueOf(jsonObject.get("code")))) {

                    //页面中部分的cookie会延迟加载
                    Thread.sleep(1000 * 2);
                    cookies = webDriver.manage().getCookies();
                    for (Cookie cookie : cookies) {
                        cookieHeader += cookie.getName()+"="+cookie.getValue()+"; ";
                    }
                    response = HttpUtil.createGet(url).addHeaders(header).execute();
                    logger.info(response.body());
                    jsonObject = JSONUtil.parseObj(response.body());
                    if (!"0".equals(String.valueOf(jsonObject.get("code")))){
                        retryShopList.add(shop);
                        webDriver.close();
                        webDriver.quit();
                        continue;
                    }
                }
                //存入店铺cookie
                List<SkShopCookie> shopCookie = new ArrayList<>();
                SkShopCookie skShopCookie = new SkShopCookie();
                skShopCookie.setCookie(cookieHeader);
                skShopCookie.setShopId(shop.getId());
                skShopCookie.setInsertTime(Integer.parseInt(String.valueOf(nowTimeMillis/1000)));
                skShopCookie.setTypes(1);
                shopCookie.add(skShopCookie);
                cookieService.saveBatch(shopCookie);
                //清空cookie
                webDriver.manage().deleteAllCookies();
                shopErrorLog(shop, "0", "", 0);
                webDriver.close();
                webDriver.quit();
            }catch (Exception e){
                retryShopList.add(shop);
                webDriver.close();
                webDriver.quit();
            }
        }

    }


    public List<ShopInfoListVo> hisHttpData(List<ShopInfoListVo> skShopInfos, Map<Long,String> shopCookie, SysUserService userService, Date yesterDay){
        if (skShopInfos.isEmpty()){
            return null;
        }
        HisKpiServiceImpl service = new HisKpiServiceImpl(); //历史数据

        List<ShopInfoListVo> reShopInfoListVo = new ArrayList<>();

        for (ShopInfoListVo shop : skShopInfos){
            logger.info("His_DATA: 店铺：" + shop.getName());
            try {

                if (!shopCookie.containsKey(shop.getId())) {
                    logger.info("店铺ID :" + shop.getId() + "未获取到Token");
                    continue;
                }
                List<String> shopAccounts = shop.getAccountInfos().stream().map(vo->{
                    return  vo.getShopAccount().trim();
                }).collect(Collectors.toList());
                //昨日的数据
                List<HisKpi> yesterData = getUrlHisData(yesterDay, shopCookie.get(shop.getId()), shopAccounts, userService, shop);
                if (!yesterData.isEmpty()){
                    service.batchInsertData(yesterData);
                }else{
                    reShopInfoListVo.add(shop);
                    continue;
                }

                //24小时前的数据
                Date fourDay = DateUtil.offsetDay(yesterDay, -1);
                List<HisKpi> fourData =  getUrlHisData(fourDay, shopCookie.get(shop.getId()), shopAccounts, userService, shop);
                if (!fourData.isEmpty()){
                    //保存数据
                    service.batchInsertData(fourData);
                }

                Date eightDay = DateUtil.offsetDay(fourDay, -1);
                List<HisKpi> eightData =  getUrlHisData(eightDay, shopCookie.get(shop.getId()), shopAccounts, userService, shop);
                if (!eightData.isEmpty()){
                    //保存数据
                    service.batchInsertData(eightData);
                }

            }catch (Exception e){

            }
        }
        return reShopInfoListVo;
    }

    /**
     * 获取历史数据
     * @param date 时间
     * @param cookie
     * @param shopAccounts
     * @param userService
     * @param shop
     * @return List<HisKpi>
     */
    public List<HisKpi> getUrlHisData(Date date, String cookie, List<String> shopAccounts, SysUserService userService, ShopInfoListVo shop){
        List<HisKpi> hisKpis = new ArrayList<>();
        try{
            JSONObject jsonObject = new JSONObject();

            String account = "";
            if (shopAccounts.size() == 1 && !StringUtils.isEmpty(shop.getAccountInfos().get(0).getUserName())){
                account = shop.getAccountInfos().get(0).getUserName();
            }

            Long timestamp = date.getTime();
            String url = String.format(hisDataUrl, timestamp , timestamp +24*60*60*1000-1, account);

            SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            //将时间转换指定格式的日期
            String terDate = f.format(timestamp);
            //昨日的数据
            Map<String, String> header = new HashMap<>();
            header.put("Cookie", cookie);
            HttpResponse response = HttpUtil.createGet(url).setConnectionTimeout(10 * 1000).setReadTimeout(5 * 1000).addHeaders(header).execute();
            logger.info(response.body());
            jsonObject = JSONUtil.parseObj(response.body());


            if ("0".equals(String.valueOf(jsonObject.get("code")))) {
                JSONObject jsonData = JSONUtil.parseObj(jsonObject.get("data"));
                Object data = jsonData.get("base_data");
                List<HisKpiDataVo> hisKpiDataVos = JSONUtil.toList(JSONUtil.parseArray(data), HisKpiDataVo.class);

                //String finalUserNames = getUserNames(userService, shop.getUserIds());
                hisKpiDataVos.forEach(his -> {
                    if (shopAccounts.contains(his.getStaff_username())) {
                        HisKpi hisKpi = new HisKpi();
                        hisKpi.setStaffName(his.getStaffName()); //客服昵称
                        hisKpi.setStaffUsername(his.getStaff_username()); //子账号
                        hisKpi.setLaborUserAmount(his.getLaborUserAmount()); //人工已接待数量
                        hisKpi.setLaborAmount(his.getLaborAmount()); //人工已接待会话数
                        hisKpi.setAlarmConversationAmount(his.getAlarmConversationAmount()); //CPD
                        hisKpi.setDissatisfactionRate(his.getDissatisfactionRate()); //不满意率
                        hisKpi.setThreeMinResponseConRate(his.getThreeMinResponseConRate()); //三分钟人工回复率(3分钟人工回复率（会话）)
                        hisKpi.setSatisfactionRate(his.getSatisfactionRate()); //满意率
                        String firstResolutionRate = his.getFirstResolutionRate();
                        if (StringUtils.isEmpty(his.getFirstResolutionRate())){
                            firstResolutionRate = "-";
                        }
                        hisKpi.setFcrRate(firstResolutionRate);
                        hisKpi.setThreeMinResponseRate(TimeUtil.dateConversion(his.getThreeMinResponseRate()));//三分钟响应率(3分钟人工回复率（消息）)
                        hisKpi.setFirstResponseDuration(TimeUtil.dateConversion(his.getFirstResponseDuration())); //首次响应时长
                        hisKpi.setAvgResponseDuration(TimeUtil.dateConversion(his.getAvgResponseDuration()));//新平均响应时长
                        hisKpi.setInquirerAmount(his.getInquirerAmount()); //询单人数
                        hisKpi.setCreateOrderAmount(his.getCreateOrderAmount()); //下单人数
                        hisKpi.setPurchasersAmount(his.getPurchasersAmount()); //支付人数
                        hisKpi.setInquiryConversionRate(his.getInquiryConversionRate()); //询单转化率
                        hisKpi.setSalesAmount(his.getSalesAmount()); //销售金额
                        hisKpi.setOnlineDuration(TimeUtil.dateConversion(his.getOnlineDuration())); //PC在线时长
                        hisKpi.setNapDuration(TimeUtil.dateConversion(his.getNapDuration())); //PC小休时长
                        hisKpi.setOfflineDuration(TimeUtil.dateConversion(his.getOfflineDuration())); //PC离线时长
                        hisKpi.setInsertTime(terDate);
                        hisKpi.setInsertTimestamp(timestamp);
                        hisKpi.setUserId(shop.getUserId());
                        hisKpi.setUserName(shop.getUserName());
                        hisKpi.setShopId(shop.getId());
                        hisKpi.setShopName(shop.getName());
                        hisKpi.setUserIds(shop.getUserIds());
                        //hisKpi.setUserNames(finalUserNames);
                        hisKpi.setDeptId(shop.getDeptId());
                        hisKpi.setDeptIds(shop.getDeptIds());
                        hisKpi.setDeptNames(shop.getDeptNames());
                        hisKpi.setPlatform(ShopPlatformEnum.DOUYIN);
                        hisKpi.setBusinessManagerIds(shop.getBusinessManagerIds());
                        hisKpi.setBusinessManagerNames(shop.getBusinessManagerNames());
                        hisKpi.setBaseManagerIds(shop.getBaseManagerIds());
                        hisKpi.setBaseManagerNames(shop.getBaseManagerNames());
                        hisKpis.add(hisKpi);
                    }
                });
            }
        }catch (Exception e){
            logger.info("请求数据:" + e);
            return null;
        }
        return hisKpis;
    }

    public List<ShopInfoListVo> realHttpData(List<ShopInfoListVo> skShopInfos, Map<Long,String> shopCookie, SysUserService userService){

        if (skShopInfos.isEmpty()){
            return null;
        }
        SkRealDataService skRealDataService = new SkRealDataServiceImpl();
        List<ShopInfoListVo> reShopInfoListVo = new ArrayList<>();

        for (ShopInfoListVo shop : skShopInfos){
            try {
                logger.info("Real_DATA: 店铺：" + shop.getName());
                Long nowTimeMillis = System.currentTimeMillis();  //时间戳

                SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                //将时间转换指定格式的日期
                String nowDate = f.format(nowTimeMillis);

                if (!shopCookie.containsKey(shop.getId())){
                    logger.info("店铺ID :" + shop.getId() + "未获取到Token");
                    continue;
                }

                List<String> shopAccounts = shop.getAccountInfos().stream().map(vo->{
                    return vo.getShopAccount().trim();
                }).collect(Collectors.toList());


                String account = "";
                if (shopAccounts.size() == 1 && !StringUtils.isEmpty(shop.getAccountInfos().get(0).getUserName())){
                    account = shop.getAccountInfos().get(0).getUserName();
                }
                String url = String.format(realDataUrl, account);

                Map<String, String> header = new HashMap<>();
                header.put("Cookie", shopCookie.get(shop.getId()));

                HttpResponse response = HttpUtil.createGet(url).setConnectionTimeout(10 * 1000).setReadTimeout(5 * 1000).addHeaders(header).execute();
                logger.info(response.body());
                JSONObject jsonObject = JSONUtil.parseObj(response.body());

                if ("0".equals(String.valueOf(jsonObject.get("code")))) {

                    List<RealDataVo> realDataVos = JSONUtil.toList(JSONUtil.parseArray(jsonObject.get("data")), RealDataVo.class);
                    List<SkRealData> realDatas = new ArrayList<>();

                    //String finalUserNames = getUserNames(userService, shop.getUserIds());
                    realDataVos.forEach(real -> {
                        if (shopAccounts.contains(real.getStaff_username())) {
                            SkRealData realData = new SkRealData();
                            realData.setStaffName(real.getStaffName());
                            realData.setUserId(shop.getUserId());
                            realData.setUserIds(shop.getUserIds());
                            realData.setUserName(shop.getUserName());
                            //realData.setUserNames(finalUserNames);
                            realData.setShopId(shop.getId());
                            realData.setShopName(shop.getName());
                            realData.setDeptId(shop.getDeptId());
                            realData.setStaffUsername(real.getStaff_username());
                            String staffStatus = real.getStaffStatus();
                            if ("1".equals(staffStatus)){
                                staffStatus = "在线";
                            }else if("0".equals(staffStatus)){
                                staffStatus = "小休";
                            }else if("2".equals(staffStatus)){
                                staffStatus = "离线";
                            }
                            realData.setStaffStatus(staffStatus);
                            realData.setSaturation(real.getSaturation());
                            realData.setInChatNum(real.getInChatNum());
                            realData.setToReplyNum(real.getToReplyNum());
                            realData.setMaxChatNum(real.getMaxChatNum());
                            realData.setLaborUserAmount(real.getEndUserChatNum());
                            realData.setEndChatNum(real.getEndChatNum());
                            realData.setFirstResponseDuration(TimeUtil.dateConversion(real.getFirstResponseDuration()));
                            realData.setAvgResponseDuration(TimeUtil.dateConversion(real.getAvgResponseDuration()));
                            realData.setDissatisfactionRate(real.getDissatisfactionRate());
                            //double转百分比
                            String threeMinResponseConRate = real.getThreeMinResponseConRate();
                            if (!"-".equals(threeMinResponseConRate)) {
                                Double doub = Double.valueOf(threeMinResponseConRate);
                                threeMinResponseConRate = String.format("%.2f", doub * 100) + "%";
                            }
                            realData.setThreeMinResponseConRate(threeMinResponseConRate);

                            String threeMinResponseRate = real.getThreeMinResponseRate();
                            if (!"-".equals(threeMinResponseRate)) {
                                Double dou = Double.valueOf(threeMinResponseRate);
                                threeMinResponseRate = String.format("%.2f", dou * 100) + "%";
                            }
                            realData.setThreeMinResponseRate(threeMinResponseRate);

                            //满意率
                            String satisfactionRate = real.getSatisfactionRate();
                            if (!"-".equals(satisfactionRate)) {
                                Double doubl = Double.valueOf(satisfactionRate);
                                satisfactionRate = String.format("%.2f", doubl * 100) + "%";
                            }
                            realData.setSatisfactionRate(satisfactionRate);

                            String inquiryConversionRate = real.getInquiryConversionRate();
                            if (!"-".equals(inquiryConversionRate)) {
                                Double doubl = Double.valueOf(inquiryConversionRate);
                                inquiryConversionRate = String.format("%.2f", doubl * 100) + "%";
                            }
                            realData.setInquiryConversionRate(inquiryConversionRate);
                            realData.setInsertTimestamp(nowTimeMillis);
                            realData.setDeptIds(shop.getDeptIds());
                            realData.setDeptNames(shop.getDeptNames());
                            realData.setBusinessManagerIds(shop.getBusinessManagerIds());
                            realData.setBusinessManagerNames(shop.getBusinessManagerNames());
                            realData.setBaseManagerIds(shop.getBaseManagerIds());
                            realData.setBaseManagerNames(shop.getBaseManagerNames());
                            realDatas.add(realData);
                        }
                    });

                    if (realDatas.isEmpty()){
                        shopErrorLog(shop, "1", "子账号未匹配", AbnormalTypeEnum.ACCOUNT_ABNORMAL);
                        continue;
                    }else{
                        if (!skRealDataService.saveBatch(realDatas)) {
                            logger.info(realDatas);
                        }
                    }
                }else{
                    if ("登录过期，请重新登录".equals(String.valueOf(jsonObject.get("msg")))){
                        shopErrorLog(shop, "2", String.valueOf(jsonObject.get("msg")), AbnormalTypeEnum.AUTH_ABNORMAL);
                        continue;
                    }else{
                        shopErrorLog(shop, "1", String.valueOf(jsonObject.get("msg")), AbnormalTypeEnum.AUTH_ABNORMAL);
                        continue;
                    }

                }
                shopErrorLog(shop, "0", "", 0);
            }catch (Exception e){
                reShopInfoListVo.add(shop);
                logger.info(e.toString());
            }
        }
        return reShopInfoListVo;
    }

    public String getUserNames(SysUserService userService, String userIdString){
        List<Long> userIds = Arrays.stream(userIdString.split(",")).map(s -> {
            return Long.valueOf(s);
        }).collect(Collectors.toList());

        List<SysUser> users = userService.listByIds(userIds);

        String userNames = "";
        for(int i = 0; i <users.size(); i++){
            if (i == users.size() - 1){
                userNames += users.get(i).getNickName();
            }else{
                userNames += users.get(i).getNickName() + ",";
            }
        }
        return userNames;
    }



    /**
     * @return WebDriver
     */
    private WebDriver webDriver(Integer userSort){
        try {
            Long now = System.currentTimeMillis();
            if (StringUtils.isEmpty(this.Ip) || this.IpTime + this.fiveMin <= now){
                this.IpTime = now;
                this.Ip = this.IpPool.get(0);
                logger.info("IP数据:" + this.Ip);
                //把第一个元素放入到队尾
                this.IpPool.remove(0);
                this.IpPool.add(this.Ip);
            }

            // 创建Chrome浏览器选项
            ChromeOptions options = new ChromeOptions();
            //options.setCapability(CapabilityType.PROXY, proxy);

         /*if (this.IpTime == 0 && StringUtils.isEmpty(this.Ip)){
            this.Ip = this.IpPool[IpSort];
            this.IpTime = now;
        }*/

        /*if (this.IpTime == 0 || this.IpTime + this.fiveMin >= now){
            this.IpTime = now;
            //this.IpSort++;
            this.Ip = HttpUtil.get(JLIp).replaceAll("\n", "");
        }*/
            // 允许所有请求  "--user-data-dir=" + clintPath + userPath

            //String userPath = "" + String.valueOf(shopId);
            //String user = "user" + String.valueOf(shopId % 10 + 3);
            /**
             * options.add_argument('--disable-dev-shm-usage')
             * options.add_argument('--no-sandbox')
             */

            options.addArguments(
                    "--remote-allow-origins=*",
                    //"--user-data-dir=" + clintPath + "Profile " + String.valueOf(userSort + 24),
                    "--user-data-dir=" + clintPath + "Profile " + String.valueOf(userSort),
                    "--disable-application-cache",
                    "--disable-cache",
                    //"--headless",
                    "--no-sandbox",
                    "--disable-dev-shm-usage",
                    "--incognito"
            );

            if (!"localhost".equals(this.Ip)){
                options.addArguments("--proxy-server=http://" + this.Ip);
            }

            // 初始化WebDriver
            System.setProperty("webdriver.chrome.driver", googleDriverPath);
            return new ChromeDriver(options);
        }catch (Exception e){
            return null;
        }
    }


    private WebDriver webDriver(){
        try {
            Long now = System.currentTimeMillis();

           /* if (StringUtils.isEmpty(this.Ip) || this.IpTime + this.fiveMin <= now){
                this.IpTime = now;
                this.Ip = this.IpPool.get(0);
                logger.info("IP数据:" + this.Ip);
                //把第一个元素放入到队尾
                this.IpPool.remove(0);
                this.IpPool.add(this.Ip);
            }*/

            // 创建Chrome浏览器选项
            ChromeOptions options = new ChromeOptions();

            options.addArguments(
                    "--remote-allow-origins=*",
                    //"--profile-directory=Profile 16",
                    "--disable-application-cache",
                    "--disable-cache",
                    //"--headless",
                    "--no-sandbox",
                    "--disable-dev-shm-usage",
                    "--incognito"
            );

            options.addArguments("--proxy-server=http://" + this.IpPool.get(0));
            // 初始化WebDriver
            System.setProperty("webdriver.chrome.driver", googleDriverPath);
            return new ChromeDriver(options);
        }catch (Exception e){
            return null;
        }
    }

    /**
     * 滑块登录
     * @param webDriver
     * @param javascriptExecutor
     * @param nowTimeMillis
     */
    private Boolean login(WebDriver webDriver, JavascriptExecutor javascriptExecutor, SkShopInfo shop, Long nowTimeMillis){
        try {
            // 启动需要打开的网页
            webDriver.get(url);

            if (!sleepElement(webDriver, By.className("switch-type-switch"))){
                return false;
            }
            if (!sleepElement(webDriver, By.className("email"))){
                return false;
            }

            webDriver.findElement(By.className("switch-type-switch")).findElement(By.className("email")).click();
            List<WebElement> webElements = webDriver.findElements(By.tagName("input"));
            webElements.get(0).sendKeys(shop.getAccount()); //名称
            webElements.get(1).sendKeys(shop.getPassword()); //密码
            webElements.get(3).click(); //协议

            webDriver.findElement(By.className("account-center-submit")).findElement(By.tagName("button")).click();

            //等待滑块页面加载完 (页面中可能不存在滑块验证)
            if (sleepElement(webDriver, By.tagName("iframe"))){
                List<WebElement> iframes = webDriver.findElements(By.tagName("iframe"));

                webDriver.switchTo().frame(iframes.get(0));

                //滑块移动
                Actions actions = new Actions(webDriver);
                List<WebElement> captchaSliderBtn = new ArrayList<>();
                int eleSize = 0;
                int chickNum = 0;
                do{
                    if (chickNum > 0){
                        if (chickNum >= 6){
                            return false;
                        }
                        Thread.sleep(1000 * 3);
                    }else{
                        //第一次进来的时候 阻塞
                        if (!sleepElement(webDriver, By.className("vc-captcha-verify-visibility"))){
                            return false;
                        }else {
                            if (!sleepElement(webDriver, By.className("dragger-item"))) {
                                return false;
                            }
                        }
                    }

                    //验证码出错直接退出
                    if (webDriver.findElements(By.className("verify-message-tit")).size() > 0){
                        return false;
                    }

                    captchaSliderBtn = webDriver.findElements(By.className("dragger-item"));

                    if (captchaSliderBtn.size() > 0){
                        List<String> imgPath = saveImage(webDriver, shop.getId(), nowTimeMillis, javascriptExecutor);

                        Opencv opencv = new Opencv();
                        double distance = opencv.regex(imgPath.get(0), imgPath.get(1));
                        actions.clickAndHold(captchaSliderBtn.get(0));

                        int dis = (int)distance;
                        if (dis <= 20){  //少于10的距离跳过
                            actions.moveByOffset(20, -3);
                        }else{
                            List<Integer> numbers = rangNumberEight(dis);

                            Random random = new Random();
                            numbers.forEach(s->{
                                actions.moveByOffset(s, random.nextInt(9)-4);
                            });
                        }


                        actions.release();
                        actions.perform();

                        File file = new File(imgPath.get(0));
                        if (file.exists()){
                            file.delete();
                        }
                        File file1 = new File(imgPath.get(1));
                        if (file1.exists()){
                            file1.delete();
                        }

                        chickNum++;
                    }

                }while (captchaSliderBtn.size() > 0);

                //拖动验证是否已关闭
                if (webDriver.findElements(By.className("vc-captcha-verify-visibility")).size() > 0){
                    return false;
                }
                // 回到主窗口
                webDriver.switchTo().defaultContent();
            }

            /*List<WebElement> loginError = webDriver.findElement(By.className("account-center-message")).findElements(By.className("account-center-error-message"));
            if (loginError.size() > 0){//账号密码错误
                webDriver.quit();
                return false;
            }*/
        }catch (Exception e){
           return false;
        }
        return true;
    }

    /**
     * 阻塞标签出现
     * @param webDriver
     * @param by
     * @return
     */
    public Boolean sleepElement(WebDriver webDriver, By by){
        try {
            int eleSize = 0;
            int num = 0;
            do{
                Thread.sleep(500);
                eleSize = webDriver.findElements(by).size();
                //System.out.print(num);
                num++;
            }while (eleSize == 0 && num <= 80);
            Thread.sleep(500);
            if (num >= 80){
                return false;
            }
        }catch (Exception e){
        }
        return true;
    }

    public int checkShop(WebDriver webDriver, JavascriptExecutor javascriptExecutor, String shopName){
        try {

            String roleList = "index_roleList__39JJ7"; //"index_roleList__2YMEN"
            String roleItem = "index_roleItem__vKGup"; //index_roleItem__1-Hwe
            String leftUpperLabel = "index_leftUpperLabel__Z-ysj";  //index_leftUpperLabel__L3txl

            //解除合约
            String actionBtn = "index_actionBtn__25Mk1"; //index_actionBtn__2WDpu

            //等待页面加载
            if (!sleepElement(webDriver, By.className(roleItem))){
                Thread.sleep(5 * 1000);  //后面代理IP页面加载过慢
                if (webDriver.findElements(By.className("index_userName__16Isl")).size() == 1){
                    return 0;
                }
                return -1;
            }

            List<WebElement> shopEles = webDriver.findElement(By.className(roleList))
                    .findElements(By.className(roleItem));

            int pos = 0;
            Boolean checkShop = false;
            for (int i= 0; i < shopEles.size(); i++){

                if ("企业工作台".equals(shopEles.get(i).findElement(By.className(leftUpperLabel)).getText())){
                    continue;
                }

                if (shopName.equals(
                        shopEles.get(i).findElement(By.className("index_intro__y0tAg")).findElement(By.className("index_introName__3LLip")).getText()))
                {
                    //解除合约的直接跳过
                    if (shopEles.get(i).findElements(By.className(actionBtn)).size() > 0){
                        return -2;
                    }

                    pos = i;
                    checkShop = true;
                }
            }

            if (checkShop == false){ //店铺名称没有匹配到
                return -2;
            }

            if (pos >= 1){
                javascriptExecutor.executeScript("arguments[0].scrollIntoView(true);",shopEles.get(pos));
            }

            WebElement shopElement = shopEles.get(pos);
            if (shopElement == null){
                return -2;
            }
            shopElement.click();

            //页面加载中有延迟现象
            Thread.sleep(3 * 1000);

            if (webDriver.findElements(By.className(roleList)).size() > 0){
                return -1;
            }

        }catch (Exception e){
            return -2;
        }
        return 0;
    }

    public void checkKefu(WebDriver webDriver){
        try {
            Thread.sleep(1000 * 4);

            List<WebElement> noticeEles =  webDriver.findElements(By.className("auxo-modal-content"));
            if (noticeEles.size() > 0){
                //关闭报名商品弹窗
                List<WebElement> closeEles =noticeEles.get(0).findElements(By.className("auxo-modal-close"));
                if (closeEles.size() > 0){
                    closeEles.get(0).click();
                }

                //关闭待回复消息弹窗
                List<WebElement> footerEles = noticeEles.get(0).findElements(By.className("auxo-modal-footer"));
                if (footerEles.size() > 0){
                    List<WebElement> buttonEles = footerEles.get(0).findElements(By.tagName("button"));
                    if (buttonEles.size() > 0){
                        buttonEles.get(0).click();
                    }
                }
            }

            //关闭体验分规则升级
            /*List<WebElement> rankEles = webDriver.findElements(By.className("ecom-guide-normal-actions"));
            if (rankEles.size() > 0){
                rankEles.get(0).findElements(By.tagName("button")).get(0).click();
            }*/


            //页面中没有权限
            List<WebElement> noPermissionEles = webDriver.findElements(By.className("styles_headerTitle__308y8"));
            if (noPermissionEles.size() == 0){
                WebElement myElement = new WebDriverWait(webDriver, 20)
                        .until(new ExpectedCondition<WebElement>() {
                            @Override
                            public WebElement apply(WebDriver d) {
                                return d.findElement(By.className("ecom-guide-normal-align-left")).findElement(By.className("auxo-btn-primary"));
                            }
                        });
                //左侧弹窗
                if (myElement != null){
                    myElement.click();
                }
            }

            //右侧体验分规则升级
            List<WebElement> rightTopEles = webDriver.findElements(By.className("ecom-guide-normal-align-right"));
            if (rightTopEles.size() > 0){
                List<WebElement> buttonEles = rightTopEles.get(0).findElements(By.className("ecom-guide-normal-step-button"));

                if (buttonEles.size() > 0){
                    buttonEles.get(0).findElements(By.tagName("button")).get(0).click();
                }
            }

            webDriver.manage().window().maximize();

            List<WebElement> messageEles = webDriver.findElements(By.className("ws-arrival-drawer-header"));
            if (messageEles.size() > 0){
                messageEles.get(0).findElement(By.className("ws-arrival-drawer-close")).click();
            }

            //页面中接待按钮 有个飞鸟哪个标签
            List<WebElement> jiedaiEles = webDriver.findElements(By.className("index_headerIcon__3RUN2"));
            if (jiedaiEles.size() > 0){
                jiedaiEles.get(0).click();
            }else{
                Thread.sleep(1000);
                List<WebElement> rightEles = webDriver.findElements(By.className("nav-menu_rightBar__2FmVk"));
                if (rightEles.size() > 0){
                    rightEles.get(0).findElement(By.className("feige_headerApp__1NrTA")).findElement(By.className("feige_badge__2xELP")).click();
                }else{ //没有飞鸟标签，退出
                    webDriver.close();
                    webDriver.quit();
                    return;
                }
            }

            Thread.sleep(1000 * 8);

            //获取浏览器句柄
            Set<String> handler = webDriver.getWindowHandles();
            List<String> handlers = new ArrayList<>(handler);

            webDriver.switchTo().window(handlers.get(1));

            // 创建一个Actions对象
            Actions actions1 = new Actions(webDriver);

            Thread.sleep(1000 * 2);

            // 在页面的任何位置点击
            actions1.click().perform();

            //数据
            List<WebElement> aEles = webDriver.findElement(By.id("leftMenuTop")).findElements(By.tagName("a"));

            aEles.forEach(s->{
                WebElement menuEle = s.findElement(By.tagName("div")).findElement(By.className("NzbweV_FIvXSAFVcl2Gv"));
                if ("数据".equals(menuEle.getText())){
                    menuEle.click();
                }
            });

            Thread.sleep(1000 * 2);

            //客服数据
            List<WebElement> kefus = webDriver.findElements(By.className("ONyBRUTh4U7VR2w_qj9n"));
            kefus.get(1).click();
        }catch (Exception e){

        }
    }

    private Integer emptyStringTwoZero(String string){

        try {
            Pattern p = Pattern.compile("\\d+");
            Matcher m = p.matcher(string);
            return Integer.valueOf(m.group());
        }catch (Exception e){
            return 0;
        }
    }

    public List<String> saveImage(WebDriver webDriver, Long shopId, Long nowTimeMillis, JavascriptExecutor javascriptExecutor){

        String nowTime = String.valueOf(nowTimeMillis);
        String shopIdStr = String.valueOf(shopId);

        String qkImg = nowTime + "_" + shopIdStr + "s.png";
        String bigImg = nowTime + "_" + shopIdStr +  "b.png";

        //小图
        Image image = new Image();

        Boolean imageSave = false;
        int imageNum = 0;
        do{
            String smallPic = webDriver.findElement(By.id("captcha-verify_img_slide")).getAttribute("src");
            imageSave = image.save(smallPic, qkImg);
            imageNum++;
        }while (!imageSave && imageNum<10);

        //保存canvas图片到本地
        WebElement canvas = webDriver.findElement(By.id("captcha_verify_image"));
        if (StringUtils.isEmpty(canvas.getAttribute("src"))){

            // 执行JavaScript脚本来获取base64编码的图片
            String base64Png = (String) javascriptExecutor.executeScript("return arguments[0].toDataURL('image/png').substring(22);", canvas);

            // 解码base64编码的字符串
            byte[] data = Base64.getDecoder().decode(base64Png);

            // 创建文件
            Path path = Paths.get(bigImg);
            File imgFile = path.toFile();

            // 写入文件
            try (FileOutputStream fos = new FileOutputStream(imgFile)) {
                fos.write(data);
            }catch (Exception e){

            }
        }else{  //20240516 抖音登录的方式改成两个缺口的图片方式
            do{
                String bigPic =canvas.getAttribute("src");
                imageSave = image.save(bigPic, bigImg);
                imageNum++;
            }while (!imageSave && imageNum<10);
        }

        return Arrays.asList(qkImg,bigImg);
    }

    private List<Integer> rangNumberEight(Integer number){
        List<Integer> num = new ArrayList<>();

        //平均数
        Integer build = (number/8);
        Integer sum = 0;
        Random random = new Random();
        for(int i = 0; i < 8; i++) {
            if (i == 7){
                Integer rang = number - sum;
                num.add(rang);
            }else{
                Integer rang = random.nextInt(build);
                num.add(rang);
                sum += rang;
            }
        }
        return num;
    }

    /**
     * 保存账号下面的店铺信息
     * @param accounts List 账号（s）
     */
    public void multiSaveShop(List<SkAccounts> accounts, Long date){
        if (ObjectUtil.isEmpty(accounts)){
            return;
        }


        this.IpPool = ipPool(); //初始化IP列表
        this.Ip = this.IpPool.get(this.IpPool.size() - 1); //初始化IP
        this.IpTime = System.currentTimeMillis(); //初始化时间
        try {

            ThreadPoolExecutor fixedThreadPool = new ThreadPoolExecutor(5, 5, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
            fixedThreadPool.allowCoreThreadTimeOut(true);

            List<WebDriverListDto> driverListDtos = new ArrayList<>();

            for (SkAccounts account : accounts) {

                Future<?> future = fixedThreadPool.submit(new Runnable() {

                    @Override
                    public void run() {
                        Integer sort = getUserSort(); //获取用户的编号

                        WebDriver webDriver = webDriver(sort);
                        if (webDriver == null){
                            return;
                        }
                        try {

                            WebDriverListDto driverListDto = new WebDriverListDto();
                            driverListDto.setCreateTime(System.currentTimeMillis());
                            driverListDto.setChildThread(Thread.currentThread());
                            driverListDto.setUserSort(sort);
                            driverListDto.setWebDriver(webDriver);
                            driverListDtos.add(driverListDto);

                            addAccountShop(account, sort, webDriver, date);

                        }catch (Exception e){

                        }finally {
                            webDriver.close();
                            webDriver.quit();
                        }

                    }
                });
            }

            fixedThreadPool.shutdown();

            while (!fixedThreadPool.awaitTermination(2 * 60 * 60, TimeUnit.SECONDS)) {
                Long nowTimeMillis = System.currentTimeMillis();  //时间戳
                driverListDtos.forEach(vo -> {
                    if (nowTimeMillis >= vo.getCreateTime() + webDriverExpiredTime){
                        if (vo.getChildThread().isAlive()){
                            logger.info("线程超时 ：" + vo);
                            if (vo.getWebDriver() != null){
                                vo.getWebDriver().quit(); //退出浏览器
                            }
                            vo.getChildThread().interrupt(); //中断线程

                        }
                        driverListDtos.remove(vo);
                    }
                });

            }
        }catch (Exception e){

        }
    }

    private void addAccountShop(SkAccounts account, Integer sort, WebDriver webDriver, Long date){
        logger.info("save_shop: ：" + account.getAccount());

        Long nowTimeMillis = System.currentTimeMillis();  //时间戳

        JavascriptExecutor javascriptExecutor = (JavascriptExecutor) webDriver; //js对象
        try{

            SkShopInfo shop = new SkShopInfo();
            shop.setAccount(account.getAccount());
            shop.setPassword(account.getPassword());
            shop.setId(account.getId());

            if (!login(webDriver, javascriptExecutor, shop, nowTimeMillis)) {
                webDriver.close();
                webDriver.quit();
                logger.info("save_shop: 账号：" + account.getAccount() + "登录失败");
                incrementUserSort(sort);
                worm.accountsService.updateAccount(account.getId(), 2);
            }

            //选择店铺
            List<SkAccountShop> accountShops = checkAccountShop(webDriver, account, date);

            if (ObjectUtil.isNotEmpty(accountShops)){
                SkAccountShopServiceImpl accountShopService = new SkAccountShopServiceImpl();
                if (accountShopService.saveBatch(accountShops)){
                    worm.accountsService.updateAccount(account.getId(), 1);
                }
            }

        }catch (Exception e){
            logger.info(e.getMessage());
        }finally {
            incrementUserSort(sort);
            webDriver.close();
            webDriver.quit();
        }
    }


    public List<SkAccountShop> checkAccountShop(WebDriver webDriver, SkAccounts account, Long date){
        try {

            List<SkAccountShop> accountShops = new ArrayList<>();

            String roleList = "index_roleList__39JJ7"; //"index_roleList__2YMEN"
            String roleItem = "index_roleItem__vKGup"; //index_roleItem__1-Hwe
            String leftUpperLabel = "index_leftUpperLabel__Z-ysj";  //index_leftUpperLabel__L3txl

            //解除合约
            String actionBtn = "index_actionBtn__25Mk1"; //index_actionBtn__2WDpu

            //等待页面加载
            if (!sleepElement(webDriver, By.className(roleList))){
                if (webDriver.findElements(By.className("index_userName__16Isl")).size() == 1){
                    SkAccountShop shop = new SkAccountShop();

                    shop.setShopName(webDriver.findElement(By.className("index_userName__16Isl")).getText());
                    shop.setPlatform(ShopPlatformEnum.DOUYIN);
                    shop.setStatus(0);
                    shop.setAccount(account.getAccount());
                    shop.setPassword(account.getPassword());
                    shop.setCreateTime(date);
                    accountShops.add(shop);

                    return accountShops;
                }
                return null;
            }
            if (!sleepElement(webDriver, By.className(roleList))){
                if (webDriver.findElements(By.className("index_userName__16Isl")).size() == 1){
                    SkAccountShop shop = new SkAccountShop();

                    shop.setShopName(webDriver.findElement(By.className("index_userName__16Isl")).getText());
                    shop.setPlatform(ShopPlatformEnum.DOUYIN);
                    shop.setStatus(0);
                    shop.setAccount(account.getAccount());
                    shop.setPassword(account.getPassword());
                    shop.setCreateTime(date);
                    accountShops.add(shop);

                    return accountShops;
                }
                return null;
            }

            List<WebElement> shopEles = webDriver.findElement(By.className(roleList))
                    .findElements(By.className(roleItem));


            for (int i= 0; i < shopEles.size(); i++){

                String shopName = shopEles.get(i).findElement(By.className("index_intro__y0tAg")).findElement(By.className("index_introName__3LLip")).getText();

                Integer status = 0;
                //解除合约
                if (shopEles.get(i).findElements(By.className(actionBtn)).size() > 0){
                    status = 1;
                }

                SkAccountShop shop = new SkAccountShop();

                shop.setShopName(shopName);
                shop.setStatus(status);
                shop.setPlatform(ShopPlatformEnum.DOUYIN);
                shop.setAccount(account.getAccount());
                shop.setPassword(account.getPassword());
                shop.setCreateTime(date);
                shop.setTypes(shopEles.get(i).findElement(By.className(leftUpperLabel)).getText());

                accountShops.add(shop);
            }

            return accountShops;
        }catch (Exception e){

        }
        return null;
    }
}
